/*
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * <rom.prevot@gmail.com> wrote this file. As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return R. Prevot
 * ----------------------------------------------------------------------------
 */

/******************************************************************************\
 *          ____                _______    _____ _             _              *
 *         |  _ \              |__   __|  / ____| |           | |             *
 *         | |_) | ___  _ __ _ __ | | ___| (___ | |_ ___   ___| | __          *
 *         |  _ < / _ \| '__| '_ \| |/ _ \\___ \| __/ _ \ / __| |/ /          *
 *         | |_) | (_) | |  | | | | | (_) |___) | || (_) | (__|   <           *
 *         |____/ \___/|_|  |_| |_|_|\___/_____/ \__\___/ \___|_|\_\          *
 *                                                                            *
\******************************************************************************/
package app;

import app.controllers.Cahier;
import app.controllers.Catalogue;
import app.controllers.Registre;
import app.views.Splash;
import app.models.Factory;
import app.views.ClientsPan;
import app.views.MainFrame;
import app.views.ReferencesPan;
import app.views.VentesPan;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import net.sf.libgrowl.Application;
import net.sf.libgrowl.GrowlConnector;
import net.sf.libgrowl.Notification;
import net.sf.libgrowl.NotificationType;

/**
 *
 * @author Ghost
 */
public class App {

    public static final String UPLOAD_PATH = "images/";
    static App instance;

    public static enum MESSAGE_TYPE {

        INFO,
        ERROR,
        WARNING;
    }
    //Panels
    ClientsPan clientsPan;
    ReferencesPan referencesPan;
    VentesPan ventesPan;
    //Controllers
    Registre registre;
    Catalogue catalogue;
    Cahier cahier;
    Splash splash;
    MainFrame mainFrame;
    private static Map<MESSAGE_TYPE, NotificationType> growlNotifications =
            new HashMap<MESSAGE_TYPE, NotificationType>();

    public App() {

        Tools.setDebugMode(true);

        setPLAF();

        //testGrowl();

        splash = new Splash();

        try {
            splash.setText("Connexion à la base de donnée...");
            if (!isMysqlLaunched()) {
                JOptionPane.showMessageDialog(null, "La base de donnée n'a pas été "
                        + "trouvée!\n"
                        + "Relancer wamp ou mysql.\n"
                        + "Relancer ensuite l'application", "Impossible de se connecter à "
                        + "la base de donnée", JOptionPane.ERROR_MESSAGE);
                System.exit(1);
            }
            Factory.getContext();
            splash.setText("Connexion réussie.");
        } catch (Exception e) {
            System.exit(1);
        }


        //Creating frame
        mainFrame = new MainFrame();

        clientsPan = new ClientsPan();
        referencesPan = new ReferencesPan();
        ventesPan = new VentesPan();

        registre = new Registre();
        catalogue = new Catalogue();
        cahier = new Cahier();

        mainFrame.addPanel(ventesPan);
        mainFrame.addPanel(referencesPan);
        mainFrame.addPanel(clientsPan);


    }

    /**
     * Initialize data
     */
    public void init() {

        initFiles();

        clientsPan.setRegistre(registre);
        referencesPan.setCatalogue(catalogue);
        ventesPan.setCahier(cahier);

        clientsPan.load(splash);
        referencesPan.load(splash);
        //en dernier! les ventes!
        ventesPan.load(splash);

        //Displaying it
        mainFrame.setVisible(true);
        splash.dispose();

        initGrowl();

    }

    private void initFiles() {
        File imgDir = new File(UPLOAD_PATH);
        if (!imgDir.isDirectory()) {
            Tools.debug(imgDir.getAbsolutePath() + " created!");
            imgDir.mkdir();
        } else {
            Tools.debug(imgDir.getAbsolutePath() + " already exists");
        }
    }

    public Catalogue getCatalogue() {
        return catalogue;
    }

    public Registre getRegistre() {
        return registre;
    }

    public Cahier getCahier() {
        return cahier;
    }

    public MainFrame getMainFrame() {
        return this.mainFrame;
    }

    public boolean isGrowlLaunched() {
        try {
            String line;
            Process p = Runtime.getRuntime().exec("tasklist.exe /fo csv /nh");
            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
            while ((line = input.readLine()) != null) {
                if (!line.trim().equals("")) {
                    // keep only the process name
                    line = line.substring(1);
                    line = line.substring(0, line.indexOf("\""));
                    if (line.equals("Growl.exe")) {
                        return true;
                    }
                }

            }
            input.close();
        } catch (Exception err) {
            err.printStackTrace();
        }
        return false;
    }

    public boolean isMysqlLaunched() {
        try {
            String line;
            Process p = Runtime.getRuntime().exec("tasklist.exe /fo csv /nh");
            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
            while ((line = input.readLine()) != null) {
                if (!line.trim().equals("")) {
                    // keep only the process name
                    line = line.substring(1);
                    line = line.substring(0, line.indexOf("\""));
                    if (line.toLowerCase().equals("mysqld.exe")) {
                        return true;
                    }
                }

            }
            input.close();
        } catch (Exception err) {
            err.printStackTrace();
        }
        return false;
    }

    private void initGrowl() {

        if (isGrowlLaunched()) {
            // connect to Growl on the given host
            GrowlConnector growl = new GrowlConnector("localhost");

            String path = "";

            // give your application a name and icon (optionally)
            Application downloadApp = new Application("BornToStock", new File("images/logo.png").getPath().replace("\\", "/"));
            //downloadApp.setIcon(getUrlFrom("resources/logo.png").getPath().replace("\\", "/"));

            System.out.println(path);
            // create reusable notification types, their names are used in the Growl settings
            NotificationType InformationType = new NotificationType("Information");
            NotificationType errorType = new NotificationType("Erreur");
            NotificationType warningType = new NotificationType("Warning");
            growlNotifications.put(MESSAGE_TYPE.INFO, InformationType);
            growlNotifications.put(MESSAGE_TYPE.ERROR, errorType);
            growlNotifications.put(MESSAGE_TYPE.WARNING, warningType);

            NotificationType[] notificationTypes = new NotificationType[]{
                InformationType,
                errorType,
                warningType
            };

            // now register the application in growl
            growl.register(downloadApp, notificationTypes);

            // create a notification with specific title and message
            Notification message = new Notification(downloadApp, InformationType, "Salut!", "Bienvenue sur BornToStock");

            // finally send the notification
            growl.notify(message);

        } else {
            Tools.debug("Growl non lancé!");
        }
    }

    private void test() {
        /*
        Reference ref = new Reference();
        ref.setDisponible(true);
        ref.setDesignation("ref de test!");
        ref.setPxAchatHT(11.1);
        ref.setPxVenteTTC(25.87);
        ref.setStock(12);
        ref.setVendu(4);
        
        javax.persistence.Query q = Factory.getContext().createNamedQuery("Categorie.findById"); 
        q.setParameter("id", 2);
        Categorie c = (Categorie)q.getSingleResult();
        
        ref.setCategorie(c);
        
        Factory.saveClient(ref);
         */
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        instance = new App();
        instance.init();
    }

    public static App getInstance() {
        return instance;
    }

    public static void displayMessage(String msg, MESSAGE_TYPE type) {
        App app = App.getInstance();
        if (app.isGrowlLaunched()) {

            // connect to Growl on the given host
            GrowlConnector growl = new GrowlConnector("localhost");

            // give your application a name and icon (optionally)
            Application downloadApp = new Application("BornToStock",
                    new File("resources/logo.png").getAbsolutePath());

            System.out.println(new File("resources/logo.png").getAbsolutePath());

            // create a notification with specific title and message
            Notification message = new Notification(downloadApp, growlNotifications.get(type), growlNotifications.get(type).getDisplayName(), msg);

            // finally send the notification
            growl.notify(message);
        } else {
            if (type == MESSAGE_TYPE.ERROR) {
                JOptionPane.showMessageDialog(null, msg, "Erreur", JOptionPane.ERROR_MESSAGE);
            } else if (type == MESSAGE_TYPE.INFO) {
                JOptionPane.showMessageDialog(null, msg, "Erreur", JOptionPane.INFORMATION_MESSAGE);
            } else if (type == MESSAGE_TYPE.WARNING) {
                JOptionPane.showMessageDialog(null, msg, "Erreur", JOptionPane.WARNING_MESSAGE);
            } else {
                JOptionPane.showMessageDialog(null, msg);
            }

        }

    }

    private static void setPLAF() {
        try {
            //UIManager.setLookAndFeel("de.javasoft.plaf.synthetica.SyntheticaSimple2DLookAndFeel");
            UIManager.setLookAndFeel("blabla.erreur.payer.celui.du.dessus.");
        } catch (Exception exe) {
            Tools.debug("LAF Error 1:" + exe);
            try {
                UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
            } catch (Exception e) {
                Tools.debug("LAF Error 2:" + e);
            }
        }
    }

    /**
     * Create an image
     * @param path
     * @return Image
     */
    public static Image createImage(String path) {
        URL imageURL = getUrlFrom(path);

        if (imageURL == null) {
            System.err.println("Resource not found: " + path);
            return null;
        } else {
            return (new ImageIcon(imageURL)).getImage();
        }
    }

    /**
     * Create an icon
     * @param path
     * @return 
     */
    public static Icon createIcon(String path) {
        URL iconURL = getUrlFrom(path);
        if (iconURL == null) {
            System.err.println("Resource not found: " + path);
            return null;
        } else {
            return (new ImageIcon(iconURL));
        }
    }

    /**
     * Get a photo from photos uploaded
     * @param name the name of the pic
     */
    public static Image createPhoto(String name) {
        if (!"".equals(name)) {
            File pix = new File(UPLOAD_PATH + name);
            try {
                if (pix.isFile()) {
                    BufferedImage bufferedImage = ImageIO.read(pix);
                    return Toolkit.getDefaultToolkit().createImage(bufferedImage.getSource());
                }
            } catch (Exception e) {
            }
        }
        return createImage("resources/no-image.gif");
    }

    /**
     * Get the url to create the image
     * @param path
     * @return url of the image
     */
    public static URL getUrlFrom(String path) {
        URL imageURL = App.class.getResource(path);
        return imageURL;
    }

    /**
     * Save a file in the app folder and return the name of the uploaded file
     * @param src
     * @return 
     */
    public static String saveFile(File src) {
        try {
            File f2 = new File(UPLOAD_PATH + src.getName());
            if(f2.isFile()){
                return f2.getName();
            }
            InputStream in = new FileInputStream(src);

            //For Append the file.
            //  OutputStream out = new FileOutputStream(f2,true);

            //For Overwrite the file.
            OutputStream out = new FileOutputStream(f2);

            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
            in.close();
            out.close();
            return f2.getName();
        } catch (Exception e) {
            Logger.getLogger(App.getInstance().getClass().toString()).log(
                    Level.SEVERE, "Impossible de copier '" + src.getAbsolutePath() + "'");
        }
        return "";
    }
}
